package systems.jMenuBuilder;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JMenuBar;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import systems.jMenuBuilder.elements.ElementsEnum;
import systems.jMenuBuilder.elements.items.CheckBoxMenuItem;
import systems.jMenuBuilder.elements.items.ItemsEnum;
import systems.jMenuBuilder.elements.items.MenuItem;
import systems.jMenuBuilder.elements.items.RadioButtonMenuItem;
import systems.jMenuBuilder.elements.menus.Menu;
import systems.jMenuBuilder.elements.separators.Separators;

public class MenuBuilder {
  private static File configFile = null;
  private static Document docXML;
  private static Element root;
  private static SAXBuilder saxBuilder;
  private static JMenuBar jMenuBar;
  private static ArrayList<Menu> jMenuList;
  private static MenuBuilder menuBuilderInstance = new MenuBuilder();
  
  
  private MenuBuilder()
  {
    String path = "./config/JMenuBuilderConfig.xml";
    configFile = new File(path);
    loadXML(configFile);
    MenuBuilder.root = MenuBuilder.docXML.getRootElement();
    createMenus();
  }

  private static void loadXML(File xmlFile)
  {
    MenuBuilder.saxBuilder = new SAXBuilder(true);
    try{
      MenuBuilder.docXML = MenuBuilder.saxBuilder.build(xmlFile);
    }catch(JDOMException e){
      System.out.println("The following file does not respect the DTD : "+xmlFile);
      e.printStackTrace();
    } catch (IOException e) {
      System.out.println("Input/Output exception with the following file : "+xmlFile);
      e.printStackTrace();
    }
  }

  /**
   * Create all the menus according to the XML file loaded (see loadXML()).
   * If there is no menu, then it will create an empty JMenuBar else the 
   * JMenuBar will contain all the created menus.
   * @return The JMenuBar created.
   */
  private static JMenuBar createMenus()
  {
    //System.out.println("Creation des menus");
    jMenuBar = new JMenuBar();
    jMenuList = new ArrayList<Menu>();
    List<Element> menuList = root.getChildren();
    //If there is no menu to create...
    if(menuList.size() == 0)
      return jMenuBar; //... we return the empty menu bar.
    
    //... else we create all the menus.
    for(Element menu : menuList)
    {
      Menu tmp = createOneMenu(menu);
      jMenuBar.add(tmp);
      jMenuList.add(tmp);
    }
    return jMenuBar;
  }

  /**
   * Create one menu and all the item attached to its according to the Element
   * <i>menu</i> given in parameter.
   * @param menu - The root element which will be use to create the menu.
   * @return The menu created.
   */
  private static Menu createOneMenu(Element menu)
  {
    //System.out.println("\tCreation d'un menu");
    /* Getting all the menu optional attributs*/
    //There is, at least, one Element : the menu name
    List<Element> itemList = menu.getChildren();
    String nameID = itemList.get(0).getValue();
    itemList.remove(0);

    String tooltipID = menu.getAttributeValue("tooltip");
    String mnemonicKey = menu.getAttributeValue("mnemonic_key");
    char mnemonicChar = 0;
    if(mnemonicKey != null)
      mnemonicChar = mnemonicKey.charAt(0);

    Menu newMenu = new Menu(nameID, tooltipID, mnemonicChar);

    /* Now we can create the items for this menu */
    //If there is still something to create ...
    if(itemList.size() > 0)
      //... for each item of the list of items ...
      for(Element item : itemList)
      {
        try{
          switch(ElementsEnum.valueOf(item.getName()))
          {
            case separator: newMenu.add(new Separators());break;
            case menu : newMenu.addSubMenu(createOneMenu(item));break;
          }
        }catch(java.lang.IllegalArgumentException e){
          createItem(item, newMenu);
        }
      }
    return newMenu;
  }
  
  private static void createItem(Element menuItemRoot, Menu menu)
  { 
    switch(ItemsEnum.valueOf(menuItemRoot.getName()))
    {
      case menuItem:              menu.addItem(new MenuItem(menuItemRoot));break;
      case checkBoxMenuItem :     menu.addItem(new CheckBoxMenuItem(menuItemRoot));break;
      case radioButtonMenuItem :  menu.addItem(new RadioButtonMenuItem(menuItemRoot));break;
    }
  }

  public static JMenuBar getMenuBar()
  {
    return jMenuBar;
  }
  
  public static ArrayList<Menu> getMenuList()
  {
    return jMenuList;
  }
  
  public static void updateMenus()
  {
    for (Menu e : jMenuList)
      e.update();
  }

  /**
   * @return the menuBuilderInstance
   */
  public static MenuBuilder getMenuBuilderInstance() {
    return menuBuilderInstance;
  }
}
